﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;

namespace Ingenious.Owl.Linq
{
    public class CodeDomHelper
    {
        public PropertyInfo GetPropertyInfo<TSource, TProperty>(TSource source,
            Expression<Func<TSource, TProperty>> propertyLambda)
        {
            Type type = typeof(TSource);

            MemberExpression member = propertyLambda.Body as MemberExpression;
            if (member == null)
                throw new ArgumentException(string.Format(
                    "Expression '{0}' refers to a method, not a property.",
                    propertyLambda.ToString()));

            PropertyInfo propInfo = member.Member as PropertyInfo;
            if (propInfo == null)
                throw new ArgumentException(string.Format(
                    "Expression '{0}' refers to a field, not a property.",
                    propertyLambda.ToString()));

            if (type != propInfo.ReflectedType &&
                !type.IsSubclassOf(propInfo.ReflectedType))
                throw new ArgumentException(string.Format(
                    "Expresion '{0}' refers to a property that is not from type {1}.",
                    propertyLambda.ToString(),
                    type));

            return propInfo;
        }

        // TODO: Handle different forms of URIs as appropriate
        public static bool TryGetClrNamespaceFromSubjectUri(Uri subjectUri, out string clrNamespaceName)
        {
            // http://en.wikipedia.org/wiki/URI_scheme

            // We use the hierarchical part of the URI to generate our CLR namespace,
            // excluding the fragment (i.e. the part after the '#')
            clrNamespaceName = NameGenerator.MakeValidCLRNamespace(subjectUri.OriginalString, false);
            
            return true;
        }

        public static bool TryGetClrTypeNameFromSubjectUri(Uri subjectUri, out string clrTypeName)
        {
            // We use the fragment to generate the type name (i.e. the
            // part after the '#')
            clrTypeName = subjectUri.Fragment;

            return true;
        }

        public static bool TryGetClrPropertyNameFromSubjectUri(Uri subjectUri, out string clrPropertyName)
        {
            // Write in CamelCase
            clrPropertyName = subjectUri.Fragment;

            return true;
        }
    }
}
